home *** CD-ROM | disk | FTP | other *** search
/ Aminet 2 / Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso / Aminet / dev / e / amigae21b.lha / Amiga_E_v2.1b / Docs / Tutorial.doc < prev    next >
Text File  |  1992-09-02  |  14KB  |  358 lines

  1.  
  2.         +-----------------------------------------------+
  3.         |                        |
  4.         |                 Amiga E v2.1b                 |
  5.         |          Compiler for The E Language          |
  6.         |           By Wouter van Oortmerssen           |
  7.         |                        |
  8.          |                    Tutorial                   |
  9.         |                        |
  10.         +-----------------------------------------------+
  11.  
  12.  
  13.         +-----------------------------------------------+
  14.         |               LANGUAGE TUTORIAL               |
  15.         +-----------------------------------------------+
  16.  
  17. This chapter will take you on a step-by-step guided tour to learn
  18. some E. As soon as you've covered the basics in this section, you may
  19. enhance your knowledge of E using Reference.doc and the examples on
  20. disk. It's best to try the examples with the compiler as you go along.
  21. It is assumed that the reader possesses some kind of knowledge of any
  22. higher programming language (like C/Pascal) to be able to omit the more
  23. obvious explanations. If you feel that you need more explanation about
  24. some feature, see reference.doc.
  25.  
  26. make sure you have installed Amiga E in your system as described
  27. in 'Compiler.doc' and compiled 'Helloworld.e' as a first test.
  28.  
  29. Ok, we'll start off easy. Doesn't it strike you as odd that there's
  30. no such command as CLS in the shell? yes? then we'll write our own:
  31.  
  32. PROC main()
  33.   WriteF('\c',12)
  34. ENDPROC
  35.  
  36. save it as 'cls.e' and compile it with 'ec cls'. then see the result.
  37. nothing shocking so far, but it gets us to two important points.
  38. first of all, you'll notice that even the smallest programs have to
  39. be put in a function, with the name "main". For now it may look
  40. superfluous, but when you start writing bigger programs, you'll notice
  41. why this is. Secondly, we learn something new about WriteF(), and
  42. what the "F" stands for. In compiling HelloWorld.e, you saw that
  43. WriteF() just prints strings to the console. Here we see that such
  44. a string may contain formatting codes introduced by a "\" and a
  45. character that says what type of formatting will take place, like
  46. "c" is for characters, and "d" for decimals. Any arguments to such
  47. a code are simply added as arguments to WriteF(). Here we print
  48. a character with ascii-code 12, which wipes the screen.
  49.  
  50. And now for something completely different.
  51. Every programmer who starts to learn a new language on the amiga wants
  52. to open his own window. Ok, so lets do that in E.
  53.  
  54. First we use the E system function OpenW() to open a window:
  55.  
  56. w:=OpenW(20,11,400,100,$200,$F,'My first window in E!',NIL,1,NIL)
  57.  
  58. The first few arguments are, of course, the coordinates. The
  59. string must be the title (you can check the exact parameters in
  60. reference.doc chapter 9D). Those two hexadecimal values are flags:
  61. the values for those are defined in the module file 'intuition/intuition'.
  62. There are two ways to use flags like that, by using the module:
  63.  
  64. MODULE 'intuition/intuition'
  65.  
  66. idcmpflags:=IDCMP_CLOSEWINDOW
  67.  
  68. or the lazy way, by just writing down the values:
  69.  
  70. idcmpflags:=$200
  71.  
  72. These methods are exact equivalents, and it's up to you to choose which
  73. one you use. Of course, an empty window is boring, so we put a line in it:
  74.  
  75. Line(20,20,50,50,2)
  76.  
  77. Line() knows from the last call to OpenW() where to draw it.
  78. We specified $200 (=IDCMP_CLOSEWINDOW) while opening our
  79. window, because we want the user to press the closegadget when he's
  80. ready watching our window. We accomplish this waiting by:
  81.  
  82. WaitIMessage(w)
  83.  
  84. This function waits for exactly one message to arrive at our window's
  85. port. And because we told intuition we only want to know about the
  86. close-gadget, this must be IDCMP_CLOSEWINDOW.
  87. Now we can close our window:
  88.  
  89. CloseW(w)
  90.  
  91. Putting all this together for our first working window-program:
  92.  
  93.  
  94. /* Opening a window in E */
  95.  
  96. DEF w
  97.  
  98. PROC main()
  99.   IF w:=OpenW(20,11,400,100,$200,$F,'My first window in E!',NIL,1,NIL)
  100.     Line(20,20,50,50,2)
  101.     WaitIMessage(w)
  102.     CloseW(w)
  103.   ENDIF
  104. ENDPROC
  105.  
  106.  
  107. Save this as 'mywindow.e' and compile it with 'ec mywindow'
  108. You'll notice that there's a small addition to our program: the
  109. IF statement. We do this to check if our window could be opened.
  110. You must _always_ check if you're allocating resources like screens,
  111. windows, libraries and memory! If the assignment in the IF-statement
  112. looks strange to you, remember that OpenW() will return NIL (=0) if
  113. it fails, and then w:=OpenW() will also evaluate to 0, which is FALSE.
  114.  
  115. Note that if you want to display text in your window, you cannot use
  116. WriteF(), because WriteF() operates on consoles (or files). however,
  117. there's a "F" function that works on rastports (an underlying structure
  118. for windows and screens and the like): TextF().
  119. For example, add after the Line() function:
  120.  
  121. TextF(20,70,'Well well, i'm writing to my window')
  122.  
  123. You can even use the Colour() function to change the front- and
  124. background colours of the text.
  125.  
  126. Now we'll get a bit more complex: we want to have gadgets in our
  127. window to perform actions. Anyone who has used gadgets in other
  128. languages knows that this means filling in tons of structures.
  129. Not so in E: We use the function Gadget() to create gadgets for us.
  130. This function needs buffers to store those structures, so we compute
  131. the required buffersize in a constant:
  132.  
  133. CONST BUFSIZE=GADGETSIZE*3
  134.  
  135. where "3" is of course the number of gadgets we wish to create.
  136. "GADGETSIZE" is a system constant that tells us how many bytes
  137. we need to store one gadget.
  138. Then we create the space as a global array:
  139.  
  140. DEF buf[BUFSIZE]:ARRAY, next
  141.  
  142. we need the variable next as a sort of dummy with the Gadget() function.
  143. now we can start creating our gadgets:
  144.  
  145. next:=Gadget(buf,NIL,1,0,20,20,100,'Gadget 1')
  146. next:=Gadget(next,buf,2,0,20,35,100,'Gadget 2')
  147. next:=Gadget(next,buf,3,0,20,50,100,'Gadget 3')
  148.  
  149. and so our complete program will look like:
  150.  
  151.  
  152.  
  153. /* Opening a window with gadgets in E */
  154.  
  155. MODULE 'intuition/intuition'
  156.  
  157. CONST BUFSIZE=GADGETSIZE*3, IFLAGS=IDCMP_CLOSEWINDOW+IDCMP_GADGETUP
  158.  
  159. DEF buf[BUFSIZE]:ARRAY,next,w,gad:PTR TO gadget
  160.  
  161. PROC main()
  162.   next:=Gadget(buf,NIL,1,0,20,20,100,'Gadget 1')
  163.   next:=Gadget(next,buf,2,0,20,35,100,'Gadget 2')
  164.   next:=Gadget(next,buf,3,0,20,50,100,'Gadget 3')
  165.   IF w:=OpenW(20,11,300,100,IFLAGS,$F,'My first window in E!',NIL,1,buf)
  166.     WHILE WaitIMessage(w)<>IDCMP_CLOSEWINDOW
  167.       gad:=MsgIaddr()
  168.       TextF(20,80,'You pressed gadget #\d',gad.userdata)
  169.     ENDWHILE
  170.     CloseW(w)
  171.   ENDIF
  172. ENDPROC
  173.  
  174.  
  175.  
  176. As you will notice, we now go the straight way of using our intuition
  177. constants by including the module. We define the constant IFLAGS for
  178. all the flags we need: this is now one more, as we also want to hear
  179. about the user pressing gadgets. The OpenW() call has also changed a
  180. little, as the last argument for gadgets, which was NIL in our previous
  181. example, is now filled. Because we now have to respond to two types
  182. of events, our WaitIMessage() construction has changed: the function
  183. returns the class of the event which we didn't use before. Now we'll
  184. only do the WHILE loop for pressed gadgets. We can get a pointer to
  185. the object that caused the event (in our case always a gadget), and
  186. we can look in the .userdata field of the gadget to see which one
  187. was pressed. The value that we find here is exactly the same as what
  188. we wrote as third argument to Gadget(), thus 1,2 or 3. then we
  189. write that value to our window with the TextF() function.
  190.  
  191. Note that to be able to read fields of a structure relative to a
  192. pointer like "gad", we need to tell the compiler what kind of object
  193. it will be pointing to. We do this with the declaration:
  194.  
  195. DEF gad:PTR TO gadget
  196.  
  197. "gad" will still be a variable like the ones we declare like "DEF gad",
  198. but the compiler will now enable us to use it as an object just like
  199. one we create ourselves.
  200.  
  201. Of course there are lots of other ways to process events. one way is
  202. to make a loop, and have each item receive one message:
  203.  
  204. class:=WaitIMessage(w)
  205.  
  206. and then use a "SELECT class" statement to check out all the
  207. different types of classes.
  208.  
  209. Now we have a pretty good picture of how to write Intuition front-ends
  210. to our programs. Another way of creating even more professional
  211. interfaces that works remarkably well with E is using the 2.0
  212. gadtools library. Using immediate lists and typed lists, you can
  213. create all sorts of gadgets (not just boolean gadgets) with little
  214. more machinery than we used before.
  215. See GadToolsDemo.e for how to create interfaces like that.
  216.  
  217. To give just a tiny example of how we can write a program that uses
  218. those lists in a powerful fashion we'll write a program that puts up
  219. a requester with a message from the command-line arguments, and returns
  220. 0 or 5 (WARN) to dos, according to the gadget selected:
  221.  
  222.  
  223. PROC main() RETURN EasyRequestArgs(0,[20,0,0,arg,'ok|cancel'],0,NIL)*5
  224.  
  225.  
  226. Yes, indeed, that's the whole program. Note that it only runs on 2.0
  227. or higher. save as 'select.e', and compile 'ec select'. now run:
  228.  
  229. 1> select Select "ok" if you wish to perform this action
  230.  
  231. This would present the requester and return a value suitable for
  232. tests in scripts ("IF WARN ...").
  233.  
  234. The compactness of this example lies in the fact that normally functions
  235. like EasyRequestArgs get pointers to structures as arguments,
  236. which have to be built up bit by bit and then given as argument to the
  237. function (see the C-example for this function in the RKRM's to see
  238. what I mean). In E there's the list-feature which is unique for
  239. procedural programming languages which enables you to build complex
  240. data structures 'on-the-fly' without separately defining them and
  241. making identifiers for them.
  242.  
  243. In this case we have created a structure of type "easystruct" (which is
  244. an object defined in 'intuition/intuition.m'), that is the second argument
  245. to the function, like:
  246.  
  247. [20,0,0,arg,'ok|cancel']:easystruct
  248.  
  249. The :<type> specifies the type of the data structure; default is :LONG,
  250. and as all fields of easystruct are again of type LONG we left the ":"
  251. spec. out. Always note that the value of such expressions is a pointer
  252. to the data structure in memory.
  253.  
  254. As a second example we'll use taglists: we'll open a screen in 2.0
  255. fashion with OpenScreenTaglist():
  256.  
  257. s:=OpenScreenTagList(0,[SA_DEPTH,8,SA_DISPLAYID,$8020,0])
  258.  
  259. As you see, we need not build up a taglist structure separately,
  260. nor need we link any varargs hacks.
  261.  
  262.  
  263. Next we'll be watching how to use library calls other than those
  264. built in (like EasyRequestArgs() we just saw from intuition):
  265. We'll be using the "asl.library" to pop up a filerequester
  266. (again, this is 2.0 and up only). This example is a short version
  267. of 'AslDemo.e', and is also featured in reference.doc in the
  268. modules chapter. Here we'll explain how it works.
  269.  
  270.  
  271. MODULE 'Asl', 'libraries/Asl'
  272.  
  273. PROC main()
  274.   DEF req:PTR TO filerequestr
  275.   IF aslbase:=OpenLibrary('asl.library',37)
  276.     IF req:=AllocFileRequest()
  277.       IF RequestFile(req) THEN WriteF('File: "\s" in "\s"\n',req.file,req.dir)
  278.       FreeFileRequest(req)
  279.     ENDIF
  280.     CloseLibrary(aslbase)
  281.   ENDIF
  282. ENDPROC
  283.  
  284.  
  285. Until recently, we only used modules to load definitions of constants
  286. and objects; now we'll use modules to define new function calls.
  287.  
  288. as you see from the module statement, the modules that define
  289. library calls are in the root of emodules: while all other definitions
  290. are in the specific directories (read all about that in reference.doc).
  291.  
  292. Such a module provides us with a variable for the base address of
  293. the library: usually this is <libname>+"base". in this example,
  294. we have to fill the variable aslbase with a correct value before we
  295. can use its functions, and at the end we have to close it again.
  296. As you can see, the actual usage of the library is very simple.
  297. To hear about the result, we need to check our requester structure
  298. that we got returned from AllocFileRequest() for the members
  299. req.file and req.dir . RequestFile() returns TRUE or FALSE depending
  300. on whether a file was selected in the first place.
  301.  
  302. There are lots of sources in the examples/ dir that show how to
  303. interface with other libraries in a similar fashion, for example
  304. with the great "ReqTools.library".
  305.  
  306.  
  307. In our next example we'll be developing a small utility from
  308. 'sources/utilities' step by step: DirQuick.e.
  309. It is a nice and short no-nonsense three column directory-lister.
  310.  
  311.  
  312. MODULE 'dos/dos'
  313.  
  314. PROC main()
  315.   DEF info:fileinfoblock,lock,ok,c=0
  316.   IF lock:=Lock(arg,-2)
  317.     IF Examine(lock,info)
  318.       IF info.direntrytype>0
  319.         WriteF('Directory of: \s\n',info.filename)
  320.         WHILE ExNext(lock,info)
  321.           IF info.direntrytype>0
  322.             WriteF('\e[1;32m\l\s[25]\e[0;31m',info.filename)
  323.           ELSE
  324.             WriteF('\l\s[17] \r\d[7]',info.filename,info.size)
  325.           ENDIF
  326.           WriteF(IF c++=2 THEN (c:=0)+'\n' ELSE ' ')
  327.         ENDWHILE
  328.         IF c THEN WriteF('\n')
  329.       ELSE
  330.         WriteF('No Dir!\n')
  331.       ENDIF
  332.     ENDIF
  333.     UnLock(lock)
  334.   ELSE
  335.     WriteF('What ?!?\n')
  336.   ENDIF
  337. ENDPROC
  338.  
  339. We need only one module, 'dos/dos.m' to tell us about the object
  340. "fileinfoblock". Then we encounter something new: our variable
  341. "info" is not a pointer, but has as type an object. Such a declaration
  342. gives us space on the stack for a complete fileinfoblock structure.
  343. To get to the directory, we have to try to lock its name, and then
  344. examine it. That's where our "info" block comes in: the function
  345. Examine() fills our structure with data it reads from disk. Before
  346. reading all directory entries in this fashion with ExNext(), we'll
  347. have to check if the block is a directory (if direntrytype>0).
  348. With each entry we display colour #2 for directories, and
  349. normal display (with filesize) for the files. Compare those format-
  350. strings with the output, and with the string-formatting descriptions
  351. in 'reference.doc'. With the variable "c" we check how many columns we
  352. did so far: after every 3 we write a <lf> ('\n').
  353.  
  354.  
  355. That's it for the tutorial: to learn more, read all the documentation
  356. thoroughly, and study the examples. But most of all: try your own
  357. programs!
  358.